#ifndef _h_basic
#define _h_basic

#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include "../../Eigen/Dense"
#include "../../Eigen/Eigenvalues"
#include "../../MLib/mlib.h"
#include "../../MLib/formats/image_data.h"

typedef double real_num;

//typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> MatrixF;
typedef Eigen::Matrix<real_num, Eigen::Dynamic, Eigen::Dynamic> MatrixR;
typedef Eigen::Matrix<real_num, Eigen::Dynamic, 1> VectorR;
typedef Eigen::Matrix<real_num, 1, Eigen::Dynamic> RowVectorR;
typedef Eigen::Matrix<std::complex<real_num>, Eigen::Dynamic, Eigen::Dynamic> MatrixC;

void extract_patch(const image_data &img, int x, int y, int rf_size, real_num *p);
void normalize_patch(real_num *p, int patch_size);

//void matrix_mult(const MatrixR &a, const MatrixR &b, MatrixR &c);

struct _timer
{
	int tot;
	time_t st;
	char buf[999];
	_timer(int t = -1)
	{
		tot = t;
		st = time(NULL);
	}
	char* s_string(double _s) {
		if (_s < 60) {
			sprintf(buf, "%.1lfs", _s);
			return (buf);
		}
		int s = (int) _s;
		int m = s / 60; s %= 60;
		if (m < 60) {
			sprintf(buf, "%dm %ds", m, s);
			return (buf);
		}
		int h = m / 60; m %= 60;
		if (h < 24) {
			sprintf(buf, "%dh %dm %ds", h, m, s);
			return (buf);
		}
		int d = h / 24; h %= 60;
		sprintf(buf, "%dd %dh %dm %ds", d, h, m, s);
		return (buf);
	}
	char* predict(int cur)
	{
		time_t t = time(NULL);
		double s = (double) (t - st);
		if (tot < 0 || cur == 0) {
			sprintf(buf, "UNKNOWN");
			return buf;
		}
		s = s / (double)cur * (double)(tot-cur);
		return s_string(s);
	}
	char* count()
	{
		time_t t = time(NULL);
		return s_string((double) (t - st));
	}
};

#endif
